package com.ruoyi.app.business.account;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.app.config.platform.PlatFormConfig;
import com.ruoyi.app.config.util.UserUtil;
import com.ruoyi.app.converter.CompanyAccountConverter;
import com.ruoyi.app.domain.account.CompanyAccount;
import com.ruoyi.common.core.utils.CommonUtils;
import com.ruoyi.common.core.utils.PageUtils;
import com.ruoyi.common.core.web.page.CommonPageInfo;
import com.ruoyi.service.account.entity.CompanyAccountDetailEntity;
import com.ruoyi.service.account.entity.CompanyAccountEntity;
import com.ruoyi.service.account.enums.company.ChangeTypeEnum;
import com.ruoyi.service.account.enums.platform.PlatformChangeTypeEnum;
import com.ruoyi.service.account.query.CompanyAccountQuery;
import com.ruoyi.service.account.service.CompanyAccountDetailService;
import com.ruoyi.service.account.service.CompanyAccountService;
import com.ruoyi.service.company.entity.CompanyEntity;
import com.ruoyi.service.company.service.CompanyService;
import com.ruoyi.service.project.entity.ProjectEntity;
import com.ruoyi.service.project.entity.ProjectSettleEntity;
import com.ruoyi.service.project.service.ProjectService;
import com.ruoyi.service.user.model.UserInfoModel;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * <p>
 * 作用：公司账户管理
 * </p>
 *
 * @author Zane
 * @since 2025-10-19 9:08
 */
@Component
public class CompanyAccountBusiness {

  @Resource
  private CompanyAccountService companyAccountService;
  @Resource
  private CompanyAccountDetailService companyAccountDetailService;
  @Resource
  private CompanyService companyService;
  @Resource
  private PlatformAccountBusiness platformAccountBusiness;
  @Resource
  private TransactionTemplate transactionTemplate;
  @Resource
  private PlatFormConfig platFormConfig;
  @Autowired
  private ProjectService projectService;

  public void initCompanyAccount(CompanyEntity company) {
    companyAccountService.buildCompanyAccount(company);
  }

  public void addFunds(BigDecimal amount) {
    final UserInfoModel loginUser = UserUtil.getLoginUser();
    final Long companyId = loginUser.getCompanyId();
    final CompanyAccountDetailEntity detailEntity = initCompanyAccountDetailEntity(
        companyId, amount, ChangeTypeEnum.ADD, null);
    transactionTemplate.executeWithoutResult(status -> {
      companyAccountDetailService.save(detailEntity);
      refreshCompanyAccount(detailEntity);
      platformAccountBusiness.change(amount, PlatformChangeTypeEnum.COM_YC,
          StrUtil.format("{}公司账户预存{}元", loginUser.getCompanyName(),
              CommonUtils.decimalFormatNullToBlank(amount)),
          detailEntity.getId());
    });
  }

  /**
   * 锁定金额
   *
   * @param lockedAmount 锁定金额(包含佣金系数)
   * @param comId        公司id
   * @param projectId    项目id
   */
  @Transactional(rollbackFor = Exception.class)
  public void lockAmount(BigDecimal lockedAmount, Long comId, String projectId) {
    if (lockedAmount.compareTo(BigDecimal.ZERO) <= 0) {
      throw new RuntimeException("锁定金额(包含增量锁定金额)需大于0");
    }
    //校验金额是否可用
    final CompanyAccountEntity companyAccount = getByComIdEnsureExists(comId);
    if (companyAccount.getAmount().subtract(lockedAmount).compareTo(BigDecimal.ZERO) < 0) {
      throw new RuntimeException("公司账户余额不足");
    }
    final UserInfoModel loginUser = UserUtil.getLoginUser();
    final CompanyAccountDetailEntity detailEntity = initCompanyAccountDetailEntity(
        comId, lockedAmount, ChangeTypeEnum.LOCKED, projectId);
    companyAccountDetailService.save(detailEntity);
    refreshCompanyAccount(detailEntity);
//      platformAccountBusiness.updateLockedAmount(amount, PlatformChangeTypeEnum.COM_YC,
//          StrUtil.format("{}公司账户预存{}元", loginUser.getCompanyName(),
//              CommonUtils.decimalFormatNullToBlank(amount)),
//          detailEntity.getId());
  }

  private CompanyAccountDetailEntity initCompanyAccountDetailEntity(Long comId, BigDecimal amount,
      ChangeTypeEnum changeType, String traceId) {
    final Long userId = UserUtil.getUserId();
    return initCompanyAccountDetailEntity(comId, amount, changeType, traceId, userId);
  }

  private CompanyAccountDetailEntity initCompanyAccountDetailEntity(Long comId, BigDecimal amount,
      ChangeTypeEnum changeType, String traceId, Long userId) {
    final LocalDateTime now = LocalDateTime.now();
    return new CompanyAccountDetailEntity()
        .setComId(comId)
        .setChangeAmount(amount)
        .setChangeType(changeType.getCode())
        .setChangeTypeName(changeType.getName())
        .setChangeComment(changeType.getDesc())
        .setTraceKey(traceId)
        .setCreateBy(userId)
        .setCreateTime(now)
        .setUpdateBy(userId)
        .setUpdateTime(now);
  }


  private void refreshCompanyAccount(CompanyAccountDetailEntity detailEntity) {
    final CompanyAccountEntity companyInfo = getByComIdEnsureExists(detailEntity.getComId());
    final ChangeTypeEnum changeTypeEnum = ChangeTypeEnum.valueOfCode(detailEntity.getChangeType());
    final BigDecimal changeAmount = detailEntity.getChangeAmount();
    if (changeTypeEnum.getLockedFlag().isTrue()) {
      //锁定 总金额减少，锁定金额增加
      companyInfo.setAmount(companyInfo.getAmount().subtract(changeAmount))
          .setLockedAmount(companyInfo.getLockedAmount().add(changeAmount))
      ;
    } else {
      //收入和支出
      if (changeTypeEnum.getIoFlag() > 0) {
        companyInfo.setAmount(companyInfo.getAmount().add(changeAmount));
      } else if (changeTypeEnum.getIoFlag() < 0) {
        companyInfo.setAmount(companyInfo.getAmount().subtract(changeAmount))
            .setLockedAmount(companyInfo.getLockedAmount().subtract(changeAmount))
        ;
      }
    }
    companyAccountService.updateById(companyInfo);
  }

  private CompanyAccountEntity getByComIdEnsureExists(Long comId) {
    return CommonUtils.requireNotNull(companyAccountService.getByComId(comId),
        "公司账户不存在,请联系管理员");
  }

  @Transactional(rollbackFor = Exception.class)
  public void settle(ProjectSettleEntity settle) {
    //支出
    final CompanyAccountDetailEntity payDetail = initCompanyAccountDetailEntity(
        settle.getComId(), settle.getActualDeduction(), ChangeTypeEnum.PAY,
        settle.getProjectId(), platFormConfig.getId());
    //解锁
    final CompanyAccountDetailEntity releaseDetail = initCompanyAccountDetailEntity(
        settle.getComId(), settle.getLockedAmount(), ChangeTypeEnum.RELEASE,
        settle.getProjectId(), platFormConfig.getId());
    //处理账户
    final CompanyAccountEntity comAccount = getByComIdEnsureExists(settle.getComId());
    comAccount.setAmount(comAccount.getAmount().subtract(settle.getActualDeduction()))
        .setLockedAmount(comAccount.getLockedAmount().subtract(settle.getLockedAmount()))
        .setUpdateBy(platFormConfig.getId())
        .setUpdateTime(LocalDateTime.now());
    companyAccountDetailService.saveBatch(Arrays.asList(payDetail, releaseDetail));
    companyAccountService.updateById(comAccount);
  }

  public CompanyAccountEntity getByComId(Long comId) {
    return companyAccountService.getByComId(comId);
  }

  public BigDecimal getPreDepositCurMonth() {
    return companyAccountDetailService.getPreDepositCurMonth();
  }

  /**
   * 累计预存的金额
   *
   * @return
   */
  public BigDecimal getPlatformFlows() {
    return companyAccountDetailService.getPlatformFlows();
  }

  public BigDecimal getBalance() {
    return companyAccountService.getBalance();
  }

  public BigDecimal getLockedAmount() {
    return companyAccountService.getLockedAmount();
  }

  public CommonPageInfo<CompanyAccount> companyAccountList(CompanyAccountQuery query) {
    final CommonPageInfo<CompanyAccountDetailEntity> page = PageUtils.startPage(query);
    page.initData(companyAccountDetailService.companyAccountList(query,
        UserUtil.getLoginUser().getCompanyId()));
    return convert(page);
  }

  public CommonPageInfo<CompanyAccount> companyAccountListForPlatform(CompanyAccountQuery query) {
    final CommonPageInfo<CompanyAccountDetailEntity> page = PageUtils.startPage(query);
    page.initData(companyAccountDetailService.companyAccountListForPlatform(query));
    return convert(page);
  }

  private CommonPageInfo<CompanyAccount> convert(CommonPageInfo<CompanyAccountDetailEntity> page) {
    final CommonPageInfo<CompanyAccount> result = page.convert(
        CompanyAccountConverter.INSTANCE::toSimple);
    if (CollUtil.isNotEmpty(result.getList())) {
      //补充项目名称
      final List<String> projectIds = result.getList().stream().map(CompanyAccount::getTraceKey)
          .distinct().collect(Collectors.toList());
      final Map<String, ProjectEntity> projectMap = projectService.selectMapByIds(
          projectIds);
      result.getList().forEach(item -> {
        final ProjectEntity project = projectMap.get(item.getTraceKey());
        if (project != null) {
          item.setProjectName(project.getProjectName());
        }
      });
    }
    return result;
  }
}
